// written by Ray Zeller and Alex Keybl

#include "HTMLOutputter.h"
#include "Filter.h"
#include "DayTime.h"
//#include "XMLPARSER.h"

#include <iostream>
#include <string>
#include <fstream>
#include <cstdlib>
#include <sstream>

using namespace std;
const string HEADERSTART = "<center><H1>";
const string HEADEREND = "</H1></center>";
const string HEADER2START= "<H2>";
const string HEADER2END= "</H2>";
const string TIVOO = "Tivoo";
const string HEAD1="<head>\n<link rel=\"stylesheet\" type=\"text/css\"href=\"style.css\" />\n</head>\n";
const string HEAD2="<head>\n<link rel=\"stylesheet\" type=\"text/css\"href=\"../style.css\" />\n</head>\n";
const string STARTBODY = "<body>\n";
const string ENDBODY = "</body>\n";
const string TABLETITLE = "<center><TABLE>";// BORDER CELLPADDING=2 CELLSPACING=3 WIDTH=520>";
const string ENDTABLE = "</TABLE></center";
const string NEWROW = "<TR>";
const string ENDROW = "</TR>";
const string ENDLINE = " \n";
const string TABLECELL = "<TD>";
const string TABLELABEL = "<TH>";
const string OCLOCK = ":00";
const string COLON = ":";
const string TO = " - ";
const string STARTEM = "<em>";
const string ENDEM = "</em>";
const string STARTBOLD = "<b>";
const string ENDBOLD = "</b>";
const string STARTCENTER = "<center>";
const string ENDCENTER = "</center>";
const string ARBITRARYUPPERLEFTCORNERNAME = "  <TH>\n";
const string ALLDAYEVENT = "<TH><small>Day?</small>";
const string FREE = "&nbsp;";
const string FREE2 = "free";
const string INDEXHTML = "index.html";
const string OUTPUT = "output/";
const string HTML = ".html";
const string COMMASPACE = ", ";
const string TILDA = "~";
const string TILDASPACE = "~ ";
const string TDCOLSPAN = "<TD COLSPAN=";
const string THCOLSPAN = "<TH COLSPAN=";
const string ENDBRACKET = ">";
const string AHREF = "<a href=output/";
const string ENDA = "</a>";
const string A = "A";
const string B = "B";
const string C = "C";
const string TILL = "</em> to <em>";
const string STARTLIST="<ul>";
const string ENDLIST="</ul>";
const string BULLET="<li>";
const string BACK="<H4><a href=../index.html>Back</a></H4>";
const string STARTCLASS=" class=\"";
const string ENDCLASS="\">";
const string HEADER="header";
const string CONFLICT="conflict";
const string NONEFOUND="No events found.";
const int NUMBERCOLUMNS = 60;

HTMLOutputter::HTMLOutputter()
{
}

void HTMLOutputter::getTable(vector<Event> testEvents, string prefix){
	
	string fname=beginOutput(testEvents, prefix);
	ofstream myfile (fname.c_str());
	
  	if (myfile.is_open())
  	{
  		if(prefix=="")
  			myfile<<HEAD1<<STARTBODY;
  		else
  			myfile<<HEAD2<<STARTBODY;
  		myfile<<myStringHeader;
  		beginTime(myfile, prefix);
  		
		myProcessor = Processor(testEvents);
		myOutput = myProcessor.process();
		
		for (unsigned int i=0; i<myOutput.size(); ++i) {
			makeCell(myfile, i, prefix);
		}

		myfile<<
		ENDTABLE + ENDLINE;
		
		if(prefix!="")
			myfile<<BACK;
		myfile<<ENDBODY;
		myfile.close();
	}
 	else cout << "Unable to open file";
}

void HTMLOutputter::getList(vector<Event> testEvents, string prefix){
	
	string fname=beginOutput(testEvents, prefix);
	ofstream myfile (fname.c_str());
	
  	if (myfile.is_open()) {
  		if(prefix=="")
  			myfile<<HEAD1<<STARTBODY;
  		else
  			myfile<<HEAD2<<STARTBODY;
  		//myfile<<s2.str();
  		
		myProcessor = Processor(testEvents);
		myOutput = myProcessor.process();
		vector<string> days=myProcessor.getDays();
		
		unsigned int count = 0;
		for(unsigned int i=0; i<days.size(); ++i) {
				myfile<<STARTCENTER<<HEADER2START<<days[i]<<HEADER2END << ENDCENTER<<ENDLINE<<STARTLIST;
			for (unsigned int j=0; j<myOutput[i].size();) {
				stringstream time1, time2;
				unsigned int repeats = getRepeats(i,j);
//				time1<<j << OCLOCK;
//				time2<<TILL<<j+repeats<<OCLOCK;
				if(myOutput[i][j]==FREE || containsConflicts(i, j))
					count--;
				DayTime dtStart = DayTime(testEvents[count].getStart());
				DayTime dtEnd = DayTime(testEvents[count].getEnd());
				time1<< (dtStart.getHour() + COLON + dtStart.getMinute());
				time2<<(TILL+dtEnd.getHour() + COLON + dtEnd.getMinute());
				if(myOutput[i][j]!=FREE && !containsConflicts(i, j))
					myfile<<BULLET<<STARTEM<<time1.str()<<time2.str()<<ENDEM<<TO<<testEvents[count].getDescription()
					<<ENDLINE;
				myfile<<ENDLINE;
				j+=repeats;
				count++;
			}
			myfile<<ENDLIST<<ENDLINE;
		}
		
		if(prefix!="")
			myfile<<BACK;
		myfile<<ENDBODY;
		myfile.close();
	}
 	else cout << "Unable to open file";
}

void HTMLOutputter:: makeCell(ofstream& myfile, int i, string prefix){
	if(prefix=="")
		myfile<< NEWROW << addClass(TABLECELL, HEADER) <<STARTBOLD<< makeHyperlink(myProcessor.getDays()[i], C)<<ENDBOLD <<  ENDLINE;
	else
		myfile<< NEWROW << addClass(TABLECELL, HEADER) <<STARTBOLD<< myProcessor.getDays()[i]<<ENDBOLD <<  ENDLINE;
	for (unsigned int j=0; j<myOutput[i].size();){
		unsigned int repeats = getRepeats(i,j);
		if(prefix==""&&myOutput[i][j]!=FREE) {
			beginHyperlink(myfile, i, j, A);
		}
		else if(myOutput[i][j].find(TILDA, 0)!=string::npos)
			myfile<<addClass(makeColSpan(repeats), CONFLICT) <<STARTCENTER<<myOutput[i][j]<<ENDCENTER<<ENDLINE;
		else if(myOutput[i][j]==FREE)
			myfile<<addClass(makeColSpan(repeats), FREE2)<<STARTCENTER<<myOutput[i][j]<<ENDCENTER<<ENDLINE;
		else
			myfile<<makeColSpan(repeats)<<STARTCENTER<<myOutput[i][j]<<ENDCENTER<<ENDLINE;
			
		j+=repeats;
	}
}

int HTMLOutputter::getRepeats(int i, int j){
	unsigned int repeats=1;
		string repStr=myOutput[i][j];
		
		while(j+repeats<myOutput[i].size()&&myOutput[i][j+repeats]==repStr) {
			//cout<< repeats <<") " << daysOutput[i][j+repeats]<<" ";
			 ++repeats;
		}
	return repeats;
}

string HTMLOutputter::beginOutput(vector<Event> testEvents, string prefix){
	stringstream s, s2;
	
	s2<<HEADERSTART;
	if(prefix=="") {
		s<<INDEXHTML;
		s2<<TIVOO;
	}
	else if(prefix==A) {
		s<<OUTPUT<<prefix<<testEvents[0].getHash()<<HTML;
		s2<<testEvents[0].getDescription();
	}
	else if(prefix==B) {
		stringstream time;
		time<<(int)testEvents[0].getStart()<< OCLOCK;
		s2<<time.str();
		s<<OUTPUT<<B<<(int)testEvents[0].getStart()<<HTML;
	}
	else if(prefix==C) {
		s2<<testEvents[0].printDay();
		s<<OUTPUT<<makeFileName(testEvents[0].printDay(), C);
	}
	
	s2<<HEADEREND;
	myStringHeader=s2.str();
	return s.str();
}

void HTMLOutputter::beginHyperlink(ofstream& myfile, int i, int j, string prefix){
		
	if(containsConflicts(i,j))
		myfile<<addClass(makeColSpan(getRepeats(i,j)), CONFLICT)<<STARTCENTER;
	else
		myfile<<makeColSpan(getRepeats(i,j))<<STARTCENTER;
		
	for(unsigned int z=0; z<myDescriptions.size(); z++) {
		if(z>0)
			myfile<<COMMASPACE;
		myfile<<makeHyperlink(myDescriptions[z], prefix);
		}
	myfile<<ENDCENTER<<ENDLINE;
}

void HTMLOutputter::beginTime(ofstream& myfile, string prefix){
		myfile << 
		TABLETITLE << ENDLINE<<
		NEWROW << ENDLINE<<
		ARBITRARYUPPERLEFTCORNERNAME;
		
		for(int time = 0; time < 24; time++)
				myfile<<makeRow(time, prefix);

		myfile<<ENDLINE;
		//ALLDAYEVENT<<ENDLINE;
		//myfile<<ENDROW <<NEWROW;
}


string HTMLOutputter :: makeRow(int startTime, string prefix){
	stringstream s;
	//stringstream s2;
	stringstream time;
	//stringstream endTime;
	
	time<<startTime << OCLOCK;
	//s2<<OUTPUT<<B<<startTime<<HTML;
	//cout<<"!"<<s2.str()<<":" << fileExists("output/B537.html") <<" - " << fileExists(s2.str())<<"!\n";
	
	string tLabel=addClass(makeTimeCallSpan(NUMBERCOLUMNS), HEADER);
	
	if(prefix=="") {
		s << tLabel <<STARTCENTER<< AHREF << B << startTime << HTML<<ENDBRACKET<< time.str()<<ENDA <<ENDCENTER << ENDLINE;// << TO << endTime.str() << OCLOCK<< ENDCENTER << ENDLINE;
	}
	else {
		s << tLabel <<STARTCENTER<< AHREF << B << startTime << HTML<<ENDBRACKET<< time.str()<<ENDA <<ENDCENTER << ENDLINE;// << TO << endTime.str() << OCLOCK<< ENDCENTER << ENDLINE;
	}
	return s.str();
}

string HTMLOutputter :: makeColSpan(int cols){
	stringstream s;
	s << TDCOLSPAN <<cols<<ENDBRACKET;
	return(s.str());
}

string HTMLOutputter :: makeTimeCallSpan(int cols){
	stringstream s;
	s << THCOLSPAN <<cols<<ENDBRACKET;
	return(s.str());
}

string HTMLOutputter :: makeHyperlink(string desc, string prefix) {
	stringstream s;
	s<<AHREF<<makeFileName(desc, prefix)<<ENDBRACKET<<desc<<ENDA;
	return(s.str());
}

string HTMLOutputter::makeFileName(string desc, string prefix) {
	unsigned int i=0;
	int sum=0;
	while(i<desc.size()-1) {
		sum+=((int)desc[i+1]%2+1)*(int)desc[i]+((int)desc[i]%2+2)*(int)desc[i+1];
		i+=2;
	}
	
	stringstream s;
	s<<prefix<<sum<<HTML;
	return(s.str());
}

bool HTMLOutputter::containsConflicts(int i, int j) {
	int start = 0;
	bool isTilda=false;
	vector <string> descriptions;
	while(myOutput[i][j].find(TILDA, start)!=string::npos) {
		descriptions.push_back(myOutput[i][j].substr(start,myOutput[i][j].find(TILDA, start)-start));
		start=myOutput[i][j].find(TILDA, start)+2;
		isTilda=true;
	}
	descriptions.push_back(myOutput[i][j].substr(start,myOutput[i][j].size()-start));
	myDescriptions=descriptions;
	return isTilda;
}

string HTMLOutputter::addClass(string tag, string cssClass) {
	return(tag.substr(0,tag.size()-1)+STARTCLASS+cssClass+ENDCLASS);
}

void HTMLOutputter::printBlank(string desc) {
	stringstream s, s2;
	
	s2<<HEADERSTART;
	stringstream time;
	time<<desc<< OCLOCK;
	s2<<time.str();
	s<<OUTPUT<<B<<desc<<HTML;
	
	s2<<HEADEREND;
	
	string fname=s.str();
	ofstream myfile (fname.c_str());
	
  	if (myfile.is_open())
  	{
  		myfile<<HEAD2<<STARTBODY;
  		myfile<<s2.str();
  		myfile<<NONEFOUND<<ENDLINE;
		myfile<<BACK;
		myfile<<ENDBODY;
		myfile.close();
	}
 	else cout << "Unable to open file";
}

HTMLOutputter::~HTMLOutputter()
{
}
